hook[Windows系統機制]

hook[Windows系統機制]
hook[Windows系統機制]
更多義項 ▼ 收起列表 ▲

Hook是Windows中提供的一種用以替換DOS下“中斷”的系統機制,中文譯為“掛鈎”或“鉤子”。在對特定的系統事件進行hook後,一旦發生已hook事件,對該事件進行hook的程式就會收到系統的通知,這時程式就能在第一時間對該事件做出回響。

解釋

Hook是Windows中提供的一種用以替換DOS下“中斷”的系統機制,中文譯為“掛鈎”或“鉤子”。在對特定的系統事件進行hook後,一旦發生已hook事件,對該事件進行hook的程式就會收到系統的通知,這時程式就能在第一時間對該事件做出回響。

另一解釋

鉤子(Hook),是Windows訊息處理機制的一個平台,應用程式可以在上面設定子程以監視指定視窗的某種訊息,而且所監視的視窗可以是其他進程所創建的。當訊息到達後,在目標視窗處理函式之前處理它。鉤子機制允許應用程式截獲處理window訊息或特定事件。

鉤子實際上是一個處理訊息的程式段,通過系統調用,把它掛入系統。每當特定的訊息發出,在沒有到達目的視窗前,鉤子程式就先捕獲該訊息,亦即鉤子函式先得到控制權。這時鉤子函式即可以加工處理(改變)該訊息,也可以不作處理而繼續傳遞該訊息,還可以強制結束訊息的傳遞。

Hook原理

每一個Hook都有一個與之相關聯的指針列表,稱之為鉤子鍊表,由系統來維護。這個列表的指針指向指定的,應用程式定義的,被Hook子程調用的回調函式,也就是該鉤子的各個處理子程式。當與指定的Hook類型關聯的訊息發生時,系統就把這個訊息傳遞到Hook子程。一些Hook子程可以只監視訊息,或者修改訊息,或者停止訊息的前進,避免這些訊息傳遞到下一個Hook子程或者目的視窗。最近安裝的鉤子放在鏈的開始,而最早安裝的鉤子放在最後,也就是後加入的先獲得控制權。

Windows 並不要求鉤子子程的卸載順序一定得和安裝順序相反。每當有一個鉤子被卸載,Windows 便釋放其占用的記憶體,並更新整個Hook鍊表。如果程式安裝了鉤子,但是在尚未卸載鉤子之前就結束了,那么系統會自動為它做卸載鉤子的操作。

鉤子子程是一個應用程式定義的回調函式(CALLBACK Function),不能定義成某個類的成員函式,只能定義為普通的C函式。用以監視系統或某一特定類型的事件,這些事件可以是與某一特定執行緒關聯的,也可以是系統中所有執行緒的事件。

系統鉤子與執行緒鉤子

SetWindowsHookEx()函式的最後一個參數決定了此鉤子是系統鉤子還是執行緒鉤子。

執行緒鉤子用於監視指定執行緒的事件訊息。執行緒鉤子一般在當前執行緒或者當前執行緒派生的執行緒內。

系統鉤子監視系統中的所有執行緒的事件訊息。因為系統鉤子會影響系統中所有的應用程式,所以鉤子函式必須放在獨立的動態程式庫(DLL) 中。系統自動將包含“鉤子回調函式”的DLL映射到受鉤子函式影響的所有進程的地址空間中,即將這個DLL注入了那些進程。

幾點說明:

(1)如果對於同一事件(如滑鼠訊息)既安裝了執行緒鉤子又安裝了系統鉤子,那么系統會自動先調用執行緒鉤子,然後調用系統鉤子。

(2)對同一事件訊息可安裝多個鉤子處理過程,這些鉤子處理過程形成了鉤子鏈。當前鉤子處理結束後應把鉤子信息傳遞給下一個鉤子函式。

(3)鉤子特別是系統鉤子會消耗訊息處理時間,降低系統性能。只有在必要的時候才安裝鉤子,在使用完畢後要及時卸載。

套用模式

觀察模式

最為常用,像Windows提供的SetWindowHook就是典型地為這類套用準備的。而且這也是最普遍的用法。

這個模式的特點是,在事情發生的時候,發出一個通知信息。觀察者只可以查看過程中的信息,根據自己關心的內容處理自己的業務,但是不可以更改原來的流程。

如全局鉤子中,經常使用的滑鼠訊息、鍵盤訊息的監視等套用。金山詞霸螢幕取詞的功能是一個典型的套用(具體技術可以參考此類文章)。

注入模式

這個模式和觀察模式最大的不一樣的地方在於,注入的代碼是為了擴展原始代碼的功能業務。外掛程式模式是此類模式的典型案例。

不管瘦核心的外掛程式系統(如Eclipse)還是胖核心的外掛程式系統(如Delphi、Visual Studio等IDE環境),其對外提供的外掛程式接口都是為了擴展本身系統的功能的。

這種擴展的套用方式的典型特點,就是新的擴展代碼和原來的代碼會協調處理同類業務。

替換模式

如果針對套用目的不同,可以叫修復模式或破解模式。前者是為了修改系統中的BUG,後者是為了破解原有系統的限制。

很多黑客使用此種模式,將訪問加密鎖的DLL中的導出表,替換成自己的函式,這樣跳過對軟體的控制代碼。這類套用的難點是,找出函式的參數。

這類模式的特點是,原有的代碼會被新的代碼所替換。

前面三個是基本模式,還有很多和實際套用相關的模式。

集權模式

此類模式的出現,大都是為了在全部系統中,統一處理某類事情。它的特點不在於注入的方式,而在於處理的模式。

這個模式,大都套用到某類服務上,比如鍵盤服務,滑鼠服務,印表機服務等等特定服務上。通過統一接管此類服務的訪問,限制或者協調對服務的訪問。

比如鍵盤鎖功能的實現,就是暫時關閉鍵盤的所有套用。

這類模式的特點主要會和特點服務有關聯。

修復模式

替換模式的一種,這裡強調的是其套用的目的是為了修復或擴展原有系統的功能。

破解模式

替換模式的一種,這裡強調的是其套用的目的是為了跳過原有系統的一部分代碼。如加密檢測代碼,網路檢測代碼等等。

外掛程式模式

注入模式的一種,在系統的內部直接依靠HOOK機制進行擴展業務功能。

共享模式

這類套用中,經常是為了獲取對方的數據。必然我希望獲取對方系統中,所有字元串的值。可以通過替換對方的記憶體管理器,導出所有字元串。

這個套用比較特殊。不過其特點在於,目的是達到系統之間的數據共享。

其實現,可能是觀察模式,也可能是替換模式。

VB中的Hook技術套用

一、Hook簡介

Hook這個東西有時令人又愛又怕,Hook是用來攔截系統某些訊息之用,例如說,我們想

讓系統不管在什麼地方只要按個Ctl-B便執行NotePad,或許您會使用Form的KeyPreview

,設定為True,但在其他Process中按Ctl-B呢?那就沒有用,這時就得設一個Keyboard

Hook來攔截所有Key in的鍵;再如:MouseMove的Event只在該Form或Control上有效,如果希望在Form的外面也能得知Mouse Move的訊息,那隻好使用Mouse Hook來欄截Mouse

的訊息。再如:您想記錄方才使用者的所有鍵盤動作或Mosue動作,以便錄巨集,那就

使用JournalRecordHook,如果想停止所有Mosue鍵盤的動作,而放(執行)巨集,那就

使用JournalPlayBack Hook;Hook呢,可以是整個系統為範圍(Remote Hook),即其他

Process的動作您也可以攔截,也可以是LocalHook,它的攔截範圍只有Process本身。

Remote Hook的Hook Function要在.Dll之中,Local Hook則在.Bas中。

在VB如何設定Hook呢?使用SetWindowsHookEx()

Declare Function SetWindowsHookEx Lib 'user32' Alias 'SetWindowsHookExA' _

(ByVal idHook As Long, _

ByVal lpfn As Long, _

ByVal hmod As Long, _

ByVal dwThreadId As Long) As Long

idHook代表是何種Hook,有以下幾種

Public Const WH_CALLWNDPROC = 4

Public Const WH_CALLWNDPROCRET = 12

Public Const WH_CBT = 5

Public Const WH_DEBUG = 9

Public Const WH_FOREGROUNDIDLE = 11

Public Const WH_GETMESSAGE = 3

Public Const WH_HARDWARE = 8

Public Const WH_JOURNALPLAYBACK = 1

Public Const WH_JOURNALRECORD = 0

Public Const WH_KEYBOARD = 2

Public Const WH_MOUSE = 7

Public Const WH_MSGFILTER = (-1)

Public Const WH_SHELL = 10

Public Const WH_SYSMSGFILTER = 6

WH_CALLWNDPROC 當調用SendMessage時

WH_CALLWNDPROCRET 當SendMessage的調用返回時

WH_GETMESSAGE 當調用GetMessage 或 PeekMessage時

WH_KEYBOARD 當調用GetMessage 或 PeekMessage 來從訊息佇列中查詢WM_KEYUP 或 WM_KEYDOWN 訊息時

WH_MOUSE 當調用GetMessage 或 PeekMessage 來從訊息佇列中查詢滑鼠事件訊息時

WH_HARDWARE 當調用GetMessage 或 PeekMessage 來從訊息佇列種查詢非滑鼠、鍵盤訊息時

WH_MSGFILTER 當對話框、選單或滾動條要處理一個訊息時。該鉤子是局部的。它時為那些有自己的訊息處理過程的控制項對象設計的。

WH_SYSMSGFILTER 和WH_MSGFILTER一樣,只不過是系統範圍的

WH_JOURNALRECORD 當WINDOWS從硬體佇列中獲得訊息時

WH_JOURNALPLAYBACK 當一個事件從系統的硬體輸入佇列中被請求時

WH_SHELL 當關於WINDOWS外殼事件發生時,譬如任務條需要重畫它的按鈕.

WH_CBT 當基於計算機的訓練(CBT)事件發生時

WH_FOREGROUNDIDLE 由WINDOWS自己使用,一般的應用程式很少使用

WH_DEBUG 用來給鉤子函式除錯

lpfn代表Hook Function所在的Address,這是一個CallBack Fucnction,當掛上某個

Hook時,我們便得定義一個Function來當作某個訊息產生時,來處理它的Function

,這個Hook Function有一定的叄數格式

Private Function HookFunc(ByVal ncode As Long, _

ByVal wParam As Long, _

ByVal lParam As Long) As Long

nCode 代表是什麼請況之下所產生的Hook,隨Hook的不同而有不同組的可能值

wParam lParam 傳回值則隨Hook的種類和nCode的值之不同而不同。

因這個叄數是一個 Function的Address所以我們固定將Hook Function放在.Bas中,

並以AddressOf HookFunc傳入。至於Hook Function的名稱我們可以任意給定,不一

定叫 HookFunc

hmod 代表.DLL的hInstance,如果是Local Hook,該值可以是Null(VB中可傳0進去),

而如果是Remote Hook,則可以使用GetModuleHandle('.dll名稱')來傳入。

dwThreadId 代表執行這個Hook的ThreadId,如果不設定是那個Thread來做,則傳0(所以

一般來說,Remote Hook傳0進去),而VB的Local Hook一般可傳App.ThreadId進去

值回值如果SetWindowsHookEx()成功,它會傳回一個值,代表目前的Hook的Handle,

這個值要記錄下來。

因為A程式可以有一個System Hook(Remote Hook),如KeyBoard Hook,而B程式也來設一

個Remote的KeyBoard Hook,那么到底KeyBoard的訊息誰所攔截?答案是,最後的那一個

所攔截,也就是說A先做keyboard Hook,而後B才做,那訊息被B攔截,那A呢?就看B的

Hook Function如何做。如果B想讓A的Hook Function也得這個訊息,那B就得呼叫

CallNextHookEx()將這訊息Pass給A,於是產生Hook的一個連線。如果B中不想Pass這訊息

給A,那就不要呼叫CallNextHookEx()。

Declare Function CallNextHookEx Lib 'user32' _

(ByVal hHook As Long, _

ByVal ncode As Long, _

ByVal wParam As Long, _

lParam As Any) As Long

hHook值是SetWindowsHookEx()的傳回值,nCode, wParam, lParam則是Hook Procedure

中的三個叄數。

最後是將這Hook去除掉,請呼叫UnHookWindowHookEx()

Declare FunctionUnhookWindowsHookExLib 'user32' (ByVal hHook As Long) As Long

hHook便是SetWindowsHookEx()的傳回值。此時,以上例來說,B程式結束Hook,則換A可

以直接攔截訊息。

KeyBoard Hook的範例

Hook Function的三個叄數

nCode wParam lParam 傳回值

HC_ACTION 表按鍵Virtual Key 與WM_KEYDOWN同 若訊息要被處理傳0

或 反之傳1

HC_NOREMOVE

Public hHook As Long

Public Sub UnHookKBD()

If hnexthookproc <;>; 0 Then

UnhookWindowsHookExhHook

hHook = 0

End If

End Sub

Public Function EnableKBDHook()

If hHook <;>; 0 Then

Exit Function

End If

hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf MyKBHFunc, App.hInstance, App.ThreadID)

End Function

Public Function MyKBHFunc(ByVal iCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

MyKBHFunc = 0 '表示要處理這個訊息

If wParam = vbKeySnapshot Then '偵測 有沒有按到PrintScreen鍵

MyKBHFunc = 1 '在這個Hook便吃掉這個訊息

End If

Call CallNextHookEx(hHook, iCode, wParam, lParam) '傳給下一個Hook

End Function

只要將上面代碼放在VB的模組中,用標準VB程式就可以了,當運行該程式後,就能攔截所有鍵盤操作。

相關詞條

相關搜尋

熱門詞條

聯絡我們